"""
配置验证器 - 验证应用程序配置的有效性
"""

import os
import re
from pathlib import Path
from typing import List, Dict, Any, Tuple
from urllib.parse import urlparse

from logger_manager import get_logger


class ConfigValidator:
    """配置验证器"""
    
    def __init__(self):
        self.logger = get_logger("config_validator")
        self.errors = []
        self.warnings = []
    
    def validate_all(self, config: Dict[str, Any]) -> Tuple[bool, List[str], List[str]]:
        """
        验证所有配置
        
        Args:
            config: 配置字典
            
        Returns:
            (是否有效, 错误列表, 警告列表)
        """
        self.errors.clear()
        self.warnings.clear()
        
        # 验证应用配置
        if 'APP_CONFIG' in config:
            self._validate_app_config(config['APP_CONFIG'])
        
        # 验证下载配置
        if 'DOWNLOAD_CONFIG' in config:
            self._validate_download_config(config['DOWNLOAD_CONFIG'])
        
        # 验证请求头
        if 'HEADERS' in config:
            self._validate_headers(config['HEADERS'])
        
        # 验证Cookie配置
        if 'IMG_COOKIES' in config:
            self._validate_cookies(config['IMG_COOKIES'])
        
        # 验证快手配置
        if 'KUAISHOU_CONFIG' in config:
            self._validate_kuaishou_config(config['KUAISHOU_CONFIG'])
        
        is_valid = len(self.errors) == 0
        
        if is_valid:
            self.logger.info("配置验证通过")
        else:
            self.logger.error(f"配置验证失败，发现 {len(self.errors)} 个错误")
        
        if self.warnings:
            self.logger.warning(f"配置验证发现 {len(self.warnings)} 个警告")
        
        return is_valid, self.errors.copy(), self.warnings.copy()
    
    def _validate_app_config(self, app_config: Dict[str, Any]):
        """验证应用配置"""
        required_fields = ['name', 'version', 'window_size', 'download_paths']
        
        for field in required_fields:
            if field not in app_config:
                self.errors.append(f"应用配置缺少必需字段: {field}")
        
        # 验证窗口大小
        if 'window_size' in app_config:
            window_size = app_config['window_size']
            if not isinstance(window_size, (list, tuple)) or len(window_size) != 2:
                self.errors.append("window_size 必须是包含两个元素的列表或元组")
            elif not all(isinstance(x, int) and x > 0 for x in window_size):
                self.errors.append("window_size 的值必须是正整数")
        
        # 验证下载路径
        if 'download_paths' in app_config:
            self._validate_download_paths(app_config['download_paths'])
    
    def _validate_download_paths(self, download_paths: Dict[str, str]):
        """验证下载路径配置"""
        required_paths = ['douyin_video', 'douyin_image', 'kuaishou_video', 'weimiquan_image']
        
        for path_key in required_paths:
            if path_key not in download_paths:
                self.errors.append(f"下载路径配置缺少: {path_key}")
                continue
            
            path = download_paths[path_key]
            if not isinstance(path, str):
                self.errors.append(f"下载路径 {path_key} 必须是字符串")
                continue
            
            # 检查路径是否有效
            try:
                path_obj = Path(path)
                if path_obj.exists() and not path_obj.is_dir():
                    self.errors.append(f"下载路径 {path_key} 存在但不是目录: {path}")
                elif not path_obj.exists():
                    # 尝试创建目录
                    try:
                        path_obj.mkdir(parents=True, exist_ok=True)
                        self.logger.info(f"创建下载目录: {path}")
                    except Exception as e:
                        self.errors.append(f"无法创建下载目录 {path_key}: {path} - {e}")
            except Exception as e:
                self.errors.append(f"下载路径 {path_key} 无效: {path} - {e}")
    
    def _validate_download_config(self, download_config: Dict[str, Any]):
        """验证下载配置"""
        required_fields = ['chunk_size', 'timeout', 'max_retries']
        
        for field in required_fields:
            if field not in download_config:
                self.errors.append(f"下载配置缺少必需字段: {field}")
        
        # 验证块大小
        if 'chunk_size' in download_config:
            chunk_size = download_config['chunk_size']
            if not isinstance(chunk_size, int) or chunk_size <= 0:
                self.errors.append("chunk_size 必须是正整数")
            elif chunk_size < 1024:
                self.warnings.append("chunk_size 过小可能影响下载性能")
            elif chunk_size > 10 * 1024 * 1024:  # 10MB
                self.warnings.append("chunk_size 过大可能占用过多内存")
        
        # 验证超时设置
        if 'timeout' in download_config:
            timeout = download_config['timeout']
            if not isinstance(timeout, (int, float)) or timeout <= 0:
                self.errors.append("timeout 必须是正数")
            elif timeout < 5:
                self.warnings.append("timeout 过短可能导致下载失败")
        
        # 验证重试次数
        if 'max_retries' in download_config:
            max_retries = download_config['max_retries']
            if not isinstance(max_retries, int) or max_retries < 0:
                self.errors.append("max_retries 必须是非负整数")
            elif max_retries > 10:
                self.warnings.append("max_retries 过大可能导致长时间等待")
    
    def _validate_headers(self, headers: Dict[str, str]):
        """验证请求头配置"""
        required_headers = ['User-Agent']
        
        for header in required_headers:
            if header not in headers:
                self.warnings.append(f"建议添加请求头: {header}")
        
        # 验证User-Agent
        if 'User-Agent' in headers:
            user_agent = headers['User-Agent']
            if not isinstance(user_agent, str) or len(user_agent.strip()) == 0:
                self.errors.append("User-Agent 不能为空")
            elif 'Mozilla' not in user_agent:
                self.warnings.append("User-Agent 可能不够真实")
    
    def _validate_cookies(self, cookies: Dict[str, str]):
        """验证Cookie配置"""
        if not isinstance(cookies, dict):
            self.errors.append("Cookie配置必须是字典")
            return
        
        # 检查重要的Cookie字段
        important_cookies = ['sessionid', 'uid_tt']
        missing_cookies = []
        
        for cookie_name in important_cookies:
            if cookie_name not in cookies or not cookies[cookie_name]:
                missing_cookies.append(cookie_name)
        
        if missing_cookies:
            self.warnings.append(f"缺少重要Cookie: {', '.join(missing_cookies)}")
        
        # 检查Cookie值的格式
        for key, value in cookies.items():
            if not isinstance(value, str):
                self.errors.append(f"Cookie {key} 的值必须是字符串")
    
    def _validate_kuaishou_config(self, kuaishou_config: Dict[str, Any]):
        """验证快手配置"""
        required_sections = ['headers', 'cookies', 'params']
        
        for section in required_sections:
            if section not in kuaishou_config:
                self.errors.append(f"快手配置缺少部分: {section}")
        
        # 验证快手请求头
        if 'headers' in kuaishou_config:
            self._validate_headers(kuaishou_config['headers'])
        
        # 验证快手Cookie
        if 'cookies' in kuaishou_config:
            cookies = kuaishou_config['cookies']
            if 'userId' not in cookies or not cookies['userId']:
                self.warnings.append("快手配置缺少userId")
    
    def validate_url(self, url: str, platform: str = None) -> bool:
        """
        验证URL格式
        
        Args:
            url: 要验证的URL
            platform: 平台名称 (douyin, kuaishou)
            
        Returns:
            是否有效
        """
        try:
            parsed = urlparse(url)
            
            # 基本URL格式检查
            if not parsed.scheme or not parsed.netloc:
                return False
            
            # 平台特定检查
            if platform == 'douyin':
                valid_domains = ['douyin.com', 'iesdouyin.com', 'v.douyin.com']
                return any(domain in parsed.netloc for domain in valid_domains)
            elif platform == 'kuaishou':
                return 'kuaishou.com' in parsed.netloc
            
            return True
            
        except Exception:
            return False
    
    def get_validation_report(self) -> str:
        """获取验证报告"""
        report = []
        
        if self.errors:
            report.append("❌ 错误:")
            for error in self.errors:
                report.append(f"  - {error}")
        
        if self.warnings:
            report.append("⚠️ 警告:")
            for warning in self.warnings:
                report.append(f"  - {warning}")
        
        if not self.errors and not self.warnings:
            report.append("✅ 配置验证通过，没有发现问题")
        
        return "\n".join(report)


# 全局验证器实例
config_validator = ConfigValidator()


def validate_config(config: Dict[str, Any]) -> Tuple[bool, str]:
    """
    验证配置的便捷函数
    
    Args:
        config: 配置字典
        
    Returns:
        (是否有效, 验证报告)
    """
    is_valid, errors, warnings = config_validator.validate_all(config)
    report = config_validator.get_validation_report()
    return is_valid, report


def validate_url(url: str, platform: str = None) -> bool:
    """验证URL的便捷函数"""
    return config_validator.validate_url(url, platform)
